package models;

import java.io.Serializable;
import javax.persistence.*;

import prefix.util.JPAUtil;

import repository.LoanRepository;
import repository.PayRepository;

import models.LoanApp.LoanType;
import models.Transaction.Status;

import java.util.Date;
import java.util.List;

/**
 * The persistent class for the loan database table.
 * 
 */
@Entity
@Table(name = "LOAN")
public class Loan implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @TableGenerator(
            name = "LOAN_SEQ",
            table = "SEQUENCE",
            pkColumnName = "NAME",
            pkColumnValue = "LOAN_SEQ",
            valueColumnName = "CNT",
            initialValue = 10000,
            allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "LOAN_SEQ")
    @Column(unique = true, nullable = false)
    private Integer id;

    private Integer aid;

    private double amount;

    @Column(name = "APP_AMOUNT")
    private double appAmount;

    @Column(name = "APP_DURATION")
    private int appDuration;

    private double apr;

    private int duration;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "CREATE_D")
    private Date createD;

    @Column(length = 1)
    private String grade;

    @Column(name = "INT_RATE")
    private double intRate;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "ISSUE_D")
    private Date issueD;

    @Column(name = "LOAN_APP_ID")
    private Integer loanAppId;

    @Column(name = "LOAN_TYPE")
    private int loanType;

    @Column(name = "MANAGEMENT_FEE")
    private double managementFee;

    @Column(length = 100)
    private String name;

    @Column(name = "ORIG_FEE")
    private double origFee;

    @Column(name = "PAYMENT_MODE")
    private int paymentMode;

    private int purpose;

    private double rpa;

    @Column(name = "SERVICE_FEE")
    private double serviceFee;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "START_D")
    private Date startD;

    private int status;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "STATUS_D")
    private Date statusD;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "UPDATE_D")
    private Date updateD;

    @Column(name = "SUB_GRADE")
    private String subGrade;

    @Column(name = "CURRENT_PAY")
    private Integer currentPay;
    
    @Column(name="FUTURE_PAY")
    private Integer futurePay;

    public Loan() {
    }

    public enum Status {
        NEW("New"), // 0 - new loan
        INFUNDING("In Funding"), // 1 - Lenders can see it
        RELEASED_EXPIRED("Expired"), // 2 - expired, and the funds got released to the lenders
        RELEASED_REJECTED("Removed"), // 3 - Admin explicitly removed it
        ISSUED("Issued"), // 4 - borrower got his loan and money
        REVIEW_LISTING("In Review Listing"), // 5 - pulled out of listing for review
        COMPLETED("Fully Paid"), // 6 - Completely paid off
        REVIEW_EXPIRED("Partially Funded"), // 7 - Time Expired, but locking funds for potential take-partial
        RELEASED_FRAUD("Fraudulent"), // 8 - released because of fraud
        REVIEW_FINAL("In Review Final"), // 9 - final review before issuing
        CURRENT("Current"), // 10 - loan repayment is current
        GRACE_CURRENT("In Grace Period"), // 11 - payment late but with in graces period
        DELINQUENT("Late(16-30days)"), // 12 - Late payment (16-30 days late)
        INCOLLECTION("Late(31-120days)"), // 13 - payment is very late >30, sent to collection
        DEFAULTED("Default"), // 14 - determined the loan not collectable
        CHARGEDOFF("Charged Off"), // 15 - determined not collecttable and removed from lender's portfolio
        SETTLED("Settled"), // 16 - settlement has been reached between parties
        SOLD("Sold"), // 17 - debt is sold
        ANY("Internal Status"), // 18 - to be used only for admin to query any status loan
        RELEASED_UCANCEL("Withdrawn by Applicant"), // 19 - Applicant Withdrawn
        ISSUING("Loan is being issued"), // 20 - internal state. the loan is being issued
        PENDING("status before INFUNDING"), // 21
        READYTOFUND("ready to fund");// 22 -ready to put loan in funding
        private String _label = "";

        private Status(String label) {
            _label = label;
        }

        public String getLabel() {
            return _label;
        }
    }

    public LoanApp getLoanApp() {
        return LoanRepository.getSingleByProperty(LoanApp.class, "loanId", this.getId(), null);
    }

    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getAid() {
        return this.aid;
    }

    public void setAid(Integer aid) {
        this.aid = aid;
    }

    public double getAmount() {
        return this.amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }

    public double getAppAmount() {
        return this.appAmount;
    }

    public void setAppAmount(double appAmount) {
        this.appAmount = appAmount;
    }

    public int getAppDuration() {
        return this.appDuration;
    }

    public void setAppDuration(int appDuration) {
        this.appDuration = appDuration;
    }

    public double getApr() {
        return this.apr;
    }

    public void setApr(double apr) {
        this.apr = apr;
    }

    public Date getCreateD() {
        return this.createD;
    }

    public void setCreateD(Date createD) {
        this.createD = createD;
    }

    public String getGrade() {
        return this.grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }

    public double getIntRate() {
        return this.intRate;
    }

    public void setIntRate(double intRate) {
        this.intRate = intRate;
    }

    public Date getIssueD() {
        return this.issueD;
    }

    public void setIssueD(Date issueD) {
        this.issueD = issueD;
    }

    public Integer getLoanAppId() {
        return this.loanAppId;
    }

    public void setLoanAppId(Integer loanAppId) {
        this.loanAppId = loanAppId;
    }

    public LoanType getLoanType() {
        return LoanType.values()[this.loanType];
    }

    public void setLoanType(LoanType loanType) {
        this.loanType = loanType.ordinal();
    }

    public double getManagementFee() {
        return this.managementFee;
    }

    public void setManagementFee(double managementFee) {
        this.managementFee = managementFee;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getOrigFee() {
        return this.origFee;
    }

    public void setOrigFee(double origFee) {
        this.origFee = origFee;
    }

    public int getPaymentMode() {
        return this.paymentMode;
    }

    public void setPaymentMode(int paymentMode) {
        this.paymentMode = paymentMode;
    }

    public int getPurpose() {
        return this.purpose;
    }

    public void setPurpose(int purpose) {
        this.purpose = purpose;
    }

    public double getRpa() {
        return this.rpa;
    }

    public void setRpa(double rpa) {
        this.rpa = rpa;
    }

    public double getServiceFee() {
        return this.serviceFee;
    }

    public void setServiceFee(double serviceFee) {
        this.serviceFee = serviceFee;
    }

    public Date getStartD() {
        return this.startD;
    }

    public void setStartD(Date startD) {
        this.startD = startD;
    }

    public Status getStatus() {
        Status[] vals = Status.values();
        if (this.status > vals.length - 1 || this.status < 0)
            return null;
        return Status.values()[this.status];
    }

    public void setStatus(Status status) {
        this.status = status.ordinal();
    }

    public Date getStatusD() {
        return this.statusD;
    }

    public void setStatusD(Date statusD) {
        this.statusD = statusD;
    }

    public Date getUpdateD() {
        return this.updateD;
    }

    public void setUpdateD(Date updateD) {
        this.updateD = updateD;
    }

    public String getSubGrade() {
        return subGrade;
    }

    public void setSubGrade(String subGrade) {
        this.subGrade = subGrade;
    }

    public int getDuration() {
        return duration;
    }

    public void setDuration(int duration) {
        this.duration = duration;
    }

    public Integer getCurrentPayId() {
        return currentPay;
    }

    public void setCurrentPay(Integer currentPay) {
        this.currentPay = currentPay;
    }

    public Integer getFuturePay() {
        return futurePay;
    }

    public void setFuturePay(Integer futurePay) {
        this.futurePay = futurePay;
    }

    public List<Pay> getPayList() {
        return PayRepository.getListByProperty(Pay.class, "loanId", this.getId());
    }

    public Pay getCurrentPay() {
        return JPAUtil.em().find(Pay.class, this.getCurrentPayId());
    }

}